/**
 * 公共工具库，所有的公共方法都放在这里
 */

import { Modal } from 'ant-design-vue';
import mitt from 'mitt';

/**
 * 事件总线
 */
export const eventBus = mitt();

/**
 * 深拷贝
 */
export const deepClone = target => {
    const map = new WeakMap();

    function isObject(target) {
        return (typeof target === 'object' && target) || typeof target === 'function'
    }

    function clone(data) {
        if (!isObject(data)) {
            return data
        }
        if ([Date, RegExp].includes(data.constructor)) {
            return new data.constructor(data)
        }
        if (typeof data === 'function') {
            return data;
        }
        const exist = map.get(data)
        if (exist) {
            return exist;
        }
        if (data instanceof Map) {
            const result = new Map()
            map.set(data, result)
            data.forEach((val, key) => {
                if (isObject(val)) {
                    result.set(key, clone(val))
                } else {
                    result.set(key, val)
                }
            })
            return result
        }
        if (data instanceof Set) {
            const result = new Set()
            map.set(data, result)
            data.forEach(val => {
                if (isObject(val)) {
                    result.add(clone(val))
                } else {
                    result.add(val)
                }
            })
            return result
        }
        const keys = Reflect.ownKeys(data)
        const allDesc = Object.getOwnPropertyDescriptors(data)
        const result = Object.create(Object.getPrototypeOf(data), allDesc)
        map.set(data, result)
        keys.forEach(key => {
            const val = data[key]
            if (isObject(val)) {
                result[key] = clone(val)
            } else {
                result[key] = val
            }
        })
        return result
    }

    return clone(target)
}

/**
 * 防抖方法
 * @param {Function} callback 回调函数
 * @param {Number} delay 延迟执行的时间（毫秒）
 */
export const debounce = function (callback, delay = 300) {
    let timer = null; //定时器id
    return function (...args) {
        timer && clearTimeout(timer);
        timer = setTimeout(() => {
            typeof callback === 'function' && callback.apply(this, args);
        }, delay);
    }
}

/**
 * 日期格式化
 * @param {*} date 要格式化的日期
 * @param {*} format 格式化的参数
 */
export const formatDate = (date, format = 'yyyy-MM-dd HH:mm:ss') => {
    if (!(date instanceof Date)) {
        date = new Date(date);
    }
    const o = {
        "M+": date.getMonth() + 1, // 月份
        "d+": date.getDate(), // 日
        "h+": date.getHours() % 12 == 0 ? 12 : date.getHours() % 12, // 小时
        "H+": date.getHours(), // 小时
        "m+": date.getMinutes(), // 分
        "s+": date.getSeconds(), // 秒
        "q+": Math.floor((date.getMonth() + 3) / 3), // 季度
        S: date.getMilliseconds(), // 毫秒
        a: date.getHours() < 12 ? "上午" : "下午", // 上午/下午
        A: date.getHours() < 12 ? "AM" : "PM", // AM/PM
    };
    if (/(y+)/.test(format)) {
        format = format.replace(
            RegExp.$1,
            (date.getFullYear() + "").substr(4 - RegExp.$1.length)
        );
    }
    for (let k in o) {
        if (new RegExp("(" + k + ")").test(format)) {
            format = format.replace(
                RegExp.$1,
                RegExp.$1.length == 1 ? o[k] : ("00" + o[k]).substr(("" + o[k]).length)
            );
        }
    }
    return format;
}

/**
 * 绑定事件
 * @param {*} element 元素
 * @param {*} eventType 事件类型
 * @param {*} fn 方法
 */
export const bindEvent = (element, eventType, fn) => {
    if (element.addEventListener) {
        element.addEventListener(eventType, fn, false);
    } else if (element.attachEvent) { //2级DOM的事件处理 
        element.attachEvent('on' + eventType, fn);
    } else { //0级DOM的事件处理 
        element['on' + eventType] = fn;
    }
}

/**
 * 解除绑定事件
 * @param {*} element 元素
 * @param {*} eventType 事件类型
 * @param {*} fn 方法
 */
export const unbindEvent = (element, eventType, fn) => {
    if (element.removeEventListener) {
        element.removeEventListener(eventType, fn);
    } else if (element.detachEvent) { //2级DOM的事件处理 
        element.detachEvent('on' + eventType, fn);
    } else { //0级DOM的事件处理 
        element['on' + eventType] = null;
    }
}

/**
 * 是否为空
 * @param {*} value 要校验的值
 */
export const isEmpty = value => {
    if (null === value || undefined === value) return true;
    if (typeof value === 'string') {
        return value?.trim() === '' || value === `Optional('')`;
    }
    if (typeof value === 'object') {
        return !Object.keys(value).length;
    }
    return false;
}

/**
 * 转换成json对象
 * @param {*} jsonStr 要转换的字符串
 */
export const parseJSON = jsonStr => {
    const cleanedString = jsonStr.replace(/\n/g, '').trim();

    // 正则表达式匹配键值对
    const regex = /(["'`]?)([\w-]+)\1:\s*(["'`]?)([\w\s\\\/\.:-]*)\3/g;
    const config = {};

    let match;
    while ((match = regex.exec(cleanedString))) {
        const key = match[2]; // 键（去掉引号）
        let value = match[4]; // 值（去掉引号）

        // 处理值的类型
        if (/^\d+$/.test(value)) {
            value = parseInt(value, 10); // 转换为数字
        } else if (/^\d+\.\d+$/.test(value)) {
            value = parseFloat(value); // 转换为浮点数
        } else if (value === 'true' || value === 'false') {
            value = value === 'true'; // 转换为布尔值
        } else if (value === 'null') {
            value = null; // 转换为 null
        } else if (value === 'undefined') {
            value = undefined; // 转换为 undefined
        }
        config[key] = value; // 添加到对象
    }
    return config;
}

/**
 * 同步询问
 */
export const syncConfirm = (content, title, options) => {
    return new Promise((resolve, reject) => {
        Modal.confirm({
            content,
            title: title || '提示',
            onOk(close) {
                close();
                resolve();
            },
            onCancel(close) {
                typeof close === 'function' && close();
                reject();
            },
            ...options
        })
    });
}

/**
 * 询问
 */
export const asyncConfirm = (content, title, options) => {
    return new Promise((resolve, reject) => {
        Modal.confirm({
            content,
            title: title || '提示',
            onOk() {
                return new Promise(res => {
                    resolve(res);
                });
            },
            onCancel(close) {
                typeof close === 'function' && close();
                reject();
            },
            ...options
        })
    });
}

export default {
    install(app) {
        // 需要挂载的方法在此添加
        Object.assign(app.config.globalProperties, {
            $eventBus: eventBus,
            $formatDate: formatDate
        });
    }
}